package agent

import (
	"context"
	"fmt"
	"log"
	"sync"
)

// ToolManager 工具管理器
type ToolManager struct {
	tools map[string]*Tool
	mutex sync.RWMutex
}

// NewToolManager 创建新的工具管理器
func NewToolManager() *ToolManager {
	return &ToolManager{
		tools: make(map[string]*Tool),
	}
}

// RegisterTool 注册工具
func (tm *ToolManager) RegisterTool(tool *Tool) error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	if tool.Name == "" {
		return fmt.Errorf("工具名称不能为空")
	}

	if tool.Handler == nil {
		return fmt.Errorf("工具处理函数不能为空")
	}

	tm.tools[tool.Name] = tool
	log.Printf("[TOOL-MANAGER] ✅ 工具注册成功: %s", tool.Name)
	return nil
}

// GetTool 获取工具
func (tm *ToolManager) GetTool(name string) (*Tool, bool) {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	tool, exists := tm.tools[name]
	return tool, exists
}

// GetAllTools 获取所有工具
func (tm *ToolManager) GetAllTools() map[string]*Tool {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	result := make(map[string]*Tool)
	for name, tool := range tm.tools {
		result[name] = tool
	}
	return result
}

// GetToolNames 获取所有工具名称
func (tm *ToolManager) GetToolNames() []string {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	names := make([]string, 0, len(tm.tools))
	for name := range tm.tools {
		names = append(names, name)
	}
	return names
}

// UnregisterTool 注销工具
func (tm *ToolManager) UnregisterTool(name string) {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	delete(tm.tools, name)
	log.Printf("[TOOL-MANAGER] 🗑️ 工具注销: %s", name)
}

// ExecuteTool 执行工具
func (tm *ToolManager) ExecuteTool(ctx context.Context, name string, params map[string]interface{}) (string, error) {
	tool, exists := tm.GetTool(name)
	if !exists {
		return "", fmt.Errorf("工具不存在: %s", name)
	}

	log.Printf("[TOOL-MANAGER] 🔧 执行工具: %s", name)
	return tool.Handler(ctx, params)
}

// GetToolInfo 获取工具信息
func (tm *ToolManager) GetToolInfo(name string) map[string]interface{} {
	tool, exists := tm.GetTool(name)
	if !exists {
		return nil
	}

	return map[string]interface{}{
		"name":        tool.Name,
		"description": tool.Description,
		"parameters":  tool.Parameters,
	}
}

// ListTools 列出所有工具信息
func (tm *ToolManager) ListTools() []map[string]interface{} {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	tools := make([]map[string]interface{}, 0, len(tm.tools))
	for _, tool := range tm.tools {
		tools = append(tools, map[string]interface{}{
			"name":        tool.Name,
			"description": tool.Description,
			"parameters":  tool.Parameters,
		})
	}
	return tools
}

// ValidateToolCall 验证工具调用
func (tm *ToolManager) ValidateToolCall(name string, params map[string]interface{}) error {
	tool, exists := tm.GetTool(name)
	if !exists {
		return fmt.Errorf("工具不存在: %s", name)
	}

	// 验证必需参数
	for paramName, paramDef := range tool.Parameters {
		if paramDefMap, ok := paramDef.(map[string]interface{}); ok {
			if required, exists := paramDefMap["required"]; exists && required.(bool) {
				if _, hasParam := params[paramName]; !hasParam {
					return fmt.Errorf("缺少必需参数: %s", paramName)
				}
			}

			// 验证参数类型
			if paramType, exists := paramDefMap["type"]; exists {
				if paramValue, hasParam := params[paramName]; hasParam {
					if err := tm.validateParameterType(paramName, paramValue, paramType.(string)); err != nil {
						return err
					}
				}
			}
		}
	}

	return nil
}

// validateParameterType 验证参数类型
func (tm *ToolManager) validateParameterType(paramName string, value interface{}, expectedType string) error {
	switch expectedType {
	case "string":
		if _, ok := value.(string); !ok {
			return fmt.Errorf("参数 %s 应该是字符串类型", paramName)
		}
	case "number":
		switch value.(type) {
		case int, int32, int64, float32, float64:
			// 数字类型正确
		default:
			return fmt.Errorf("参数 %s 应该是数字类型", paramName)
		}
	case "boolean":
		if _, ok := value.(bool); !ok {
			return fmt.Errorf("参数 %s 应该是布尔类型", paramName)
		}
	case "array":
		// 可以添加数组类型验证
	case "object":
		// 可以添加对象类型验证
	}

	return nil
}

// GetToolStats 获取工具统计信息
func (tm *ToolManager) GetToolStats() map[string]interface{} {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	return map[string]interface{}{
		"total_tools": len(tm.tools),
		"tool_names":  tm.GetToolNames(),
	}
}
